/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package td3.Modele;

/** La classe JeuDePuissance4 possède un plateau, 2 joueurs
 * 
 * @author fredericdasilva
 */
public class JeuDePuissance4 extends Jeu{
    
    private volatile Thread tache = null;
    
    /** Le constructeur de JeuDePuissance4 construit et initialise le Plateau de Morpion
     *
     * @param a Le premier JoueurDePuissance 4
     * @param b Le second JoueurDePuissance 4
     */
    public JeuDePuissance4(Joueur a, Joueur b){
        
        super(a,b);
        P=new PlateauPuissance4();
        P.initialiser();
        
        
    }
    
    @Override
    public boolean partieTerminee(){
        
        boolean b;
        b= (P.nbCoups==P.largeur*P.longueur || AGagne());
        return b;
    }
    

    @Override
    public Joueur joueurSuivant() {
        if (P.joueurencours==J1.getId()){
            return J2;
        }
        else {
            return J1;
        }
    }
   
    @Override
    public String nomJoueurSuivant() {
        return joueurSuivant().getName();
    }
    
    @Override
    public Joueur quelleJoueur(int id){
        if (id==J1.getId()){
            return J1;
        }
        else return J2;
    }
    
    @Override
    public boolean coupPossible(Coup coup){
        boolean B=false;
        
        for (int i=0;i<P.longueur;i++){
            B= B||(P.etatIdPlateau[i][coup.y]==0);
        }
        return B;
    }
   
    @Override
    public void jouerCoupJeuJoueurHumain(Coup c, int idJeu){
        Coup boy = null;
        boy=P.appliquerCoupPuissance4(c, idJeu);
        setChanged();
        notifyObservers(boy);
   
    }
    
  
    @Override
    public void jouerCoupJeu(Coup c, int idJeu){
        Coup boy = null;
        boy=P.appliquerCoupPuissance4(c, idJeu);
        setChanged();
        
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt(); // Très important de réinterrompre
        }
        notifyObservers(boy);
        
    }
    
    @Override
    public void/*Joueur*/ jouerPartie(){
        
        Joueur retour;
        while (!this.partieTerminee()&&!this.AGagne()){
            retour =  this.joueurSuivant();
            if (retour instanceof JoueurHumain){
                //                if (this.hasChanged()){
                //                    break;
                //                }
            }
            else {
                Coup c= retour.getCoup(this.P);
                if (this.coupPossible(c)){
                    //                P.appliquerCoup(c, retour.getId());
                    this.jouerCoupJeu(c, retour.getId());
                    
                    //                jouerCoupJeuJoueurHumain(c, retour.getId());
                    System.out.println(this.P.toString());
                    System.out.println(this.P.nbCoups+" Coups joués");
                    
                }
                else {
                    c= retour.getCoup(this.P);
                    while (!this.coupPossible(c)){
                        c= retour.getCoup(this.P);
                    }
                    this.jouerCoupJeu(c, retour.getId());
                    //                jouerCoupJeuJoueurHumain(c, retour.getId());
                    System.out.println(this.P.toString());
                    System.out.println(this.P.nbCoups+" Coups joués");
                }
                
            }
            try {
                Thread.sleep(1200);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); // Très important de réinterrompre
            }
            
            
            
        }
        this.quiAGagne();
        
    }
    
    @Override
    public boolean AGagne() {
        
        boolean D=false;
        
        for (int i=0;i<=5;i++){
            for (int j=6;j>=0;j--){
                if (P.etatIdPlateau[i][j]!=0){
                    
                    //Diagonale montante à droite
                    if (i>=3&&j<=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            G=G--;
                            D=(D&&nd==P.etatIdPlateau[G][j+k]);
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    //Diagonale descendante à droite
                    if (i<3&&j<=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            G++;
                            D=(D&&nd==P.etatIdPlateau[G][j+k]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    //Diagonale descendante à gauche
                    if (i<3&&j>=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            G++;
                            D=(D&&nd==P.etatIdPlateau[G][j-k]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    //Diagonale montante à gauche
                    if (i>=3&&j>=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            G--;
                            D=(D&&nd==P.etatIdPlateau[G][j-k]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    // Verticale Descendante
                    if (i<3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            
                            D=(D&&nd==P.etatIdPlateau[G+k][j]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    // Verticale Montante
                    if (i>=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            
                            D=(D&&nd==P.etatIdPlateau[G-k][j]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    // Horizontale Gauche
                    if (j>=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            
                            D=(D&&nd==P.etatIdPlateau[G][j-k]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    // Horizontale Droite
                    if (j<=3){
                        int nd= P.etatIdPlateau[i][j];
                        int G=i;
                        D=true;
                        for (int k=1;k<=3;k++){
                            
                            D=(D&&nd==P.etatIdPlateau[G][j+k]);
                            
                        }
                        if (D){P.gagnantId = nd;
                        return D;}
                    }
                    
                    
                }
                
            }
        }
        
        
        return D;
    }
   
    @Override
    public void quiAGagne() {
        
        if (AGagne()){
            if (P.gagnantId==0) {
                
                
                
            }
            else {
                System.out.println("Le joueur "+quelleJoueur(P.gagnantId).getName()+" Id "+P.gagnantId+" a gagné");
                
            }
            
        }
        else {
            System.out.println("------------   MATCH NUL -----------------");
        }
    }
  
    @Override
    public String quiStringAGagne() {
        
        if (AGagne()){
            
            return " "+quelleJoueur(P.gagnantId).getName()+" Id "+P.gagnantId+" a gagné";
            
            
            
        }
        else {
            return "-----   MATCH NUL ----";
        }
    }
    
  
    @Override
    public void run(){
        
        
        tache = Thread.currentThread();
        if (! tache.isInterrupted())
        {
            try
            {
                
                // Tâches
                this.jouerPartie();
                
                Thread.sleep (2000);
                
            }
            catch (InterruptedException exception){
                Thread.currentThread().interrupt(); // Très important de réinterrompre
            }
        }
    }
    
    /**
     *
     */
    @Override
    public void arreter()
    {
        //        tache = Thread.currentThread();
        tache.interrupt();
    }

    @Override
    public void mise_en_attente()
    {
        //        tache = Thread.currentThread();
        tache.suspend();
    }
    
    @Override
    public void reprise()
    {
        //        tache = Thread.currentThread();
        tache.resume();
    }

    
    
    
    
}
